/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package lab1;

import java.io.*;
import java.security.acl.Group;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

/**
 *
 * @author Александр
 */
public class Manager {

    AlertList alerts = new AlertList();
    TaskList tasks = new TaskList();
    private static Manager instance = new Manager();

    public static Manager getInstance() {
        return instance;
    }

    public void startJob()  {

           
        
        JAXBContext jc1;
        JAXBContext jc2;
        try {
            jc1 = JAXBContext.newInstance(TaskList.class);
      jc2 = JAXBContext.newInstance(AlertList.class);
            InputStream is1 = new FileInputStream("TaskList.xml");
            InputStream is2 = new FileInputStream("AlertList.xml");
            Unmarshaller um1 = jc1.createUnmarshaller();
            Unmarshaller um2 = jc2.createUnmarshaller();
            this.tasks = (TaskList) um1.unmarshal(is1);
            this.alerts = (AlertList) um2.unmarshal(is2);
            is1.close();
            is2.close();
            
           
        }
        
           catch (JAXBException |  FileNotFoundException  ex) {
            Logger.getLogger(Manager.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        catch(IOException ex1){
          Logger.getLogger(Manager.class.getName()).log(Level.SEVERE, null, ex1); 
        }
        
        
//        FileInputStream fis1;
//        ObjectInputStream oin1;
//        FileInputStream fis2;
//        ObjectInputStream oin2;
//        boolean a = false;
//        boolean t = false;
//        try {
//            fis1 = new FileInputStream("temp1.bin");
//            oin1 = new ObjectInputStream(fis1);
//            this.alerts = (AlertList) oin1.readObject();
//            a = true;//если всё успешно считалось
//            fis2 = new FileInputStream("temp2.bin");
//            oin2 = new ObjectInputStream(fis2);
//            this.tasks = (TaskList) oin2.readObject();
//            t = true;//если всё успешно считалось
//        } catch (FileNotFoundException ex) {
//            try {
//                File file1 = new File("temp1.bin");
//                file1.createNewFile();
//                File file2 = new File("temp2.bin");
//                file2.createNewFile();
//                System.out.println(file1.exists());
//            } catch (IOException ex1) {
//                Logger.getLogger(Manager.class.getName()).log(Level.SEVERE, null, ex1);
//            }
//        } catch (EOFException ex) {
////            ????        }
//        } catch (ClassNotFoundException | IOException ex) {
//            Logger.getLogger(Manager.class.getName()).log(Level.SEVERE, null, ex);
//        }
    }

    
    
    
    
    
    public void endJob() {
        
        
        try{
    
            JAXBContext jc1 = JAXBContext.newInstance(TaskList.class);
            JAXBContext jc2 = JAXBContext.newInstance(AlertList.class);
            Marshaller m1 = jc1.createMarshaller();
            Marshaller m2 = jc2.createMarshaller();
            
            OutputStream os1 = new FileOutputStream("TaskList.xml");
            OutputStream os2 = new FileOutputStream("AlertList.xml");
            m1.marshal(this.tasks, os1);
            m2.marshal(this.alerts, os2);
            os1.flush();
            os1.close();
            os2.flush();
            os2.close();

        }
            catch (JAXBException |  FileNotFoundException  ex) {
            Logger.getLogger(Manager.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        catch(IOException ex1){
          Logger.getLogger(Manager.class.getName()).log(Level.SEVERE, null, ex1); 
        }
//        FileOutputStream fos1 = null;
//        ObjectOutputStream oos1 = null;
//
//        FileOutputStream fos2 = null;
//        ObjectOutputStream oos2 = null;
//        try {
//            fos1 = new FileOutputStream("temp1.bin");
//            oos1 = new ObjectOutputStream(fos1);
//            oos1.writeObject(this.alerts);
//            oos1.flush();
//            oos1.close();
//
//            fos2 = new FileOutputStream("temp2.bin");
//            oos2 = new ObjectOutputStream(fos2);
//            oos2.writeObject(this.tasks);
//            oos2.flush();
//            oos2.close();
//
//        } catch (IOException ex) {
//            Logger.getLogger(Manager.class.getName()).log(Level.SEVERE, null, ex);
//        } finally {
//            try {
//                fos1.close();
//            } catch (IOException ex) {
//                Logger.getLogger(Manager.class.getName()).log(Level.SEVERE, null, ex);
//            }
//            try {
//                oos1.close();
//            } catch (IOException ex) {
//                Logger.getLogger(Manager.class.getName()).log(Level.SEVERE, null, ex);
//            }
//
//            try {
//                fos2.close();
//            } catch (IOException ex) {
//                Logger.getLogger(Manager.class.getName()).log(Level.SEVERE, null, ex);
//            }
//            try {
//                oos2.close();
//            } catch (IOException ex) {
//                Logger.getLogger(Manager.class.getName()).log(Level.SEVERE, null, ex);
//            }
//
//        }
    }

    private boolean isDayEquals(Calendar c1, Calendar c2) {
        return ((c1.get(Calendar.YEAR) == c2.get(Calendar.YEAR))
                && c2.get(Calendar.MONTH) == c2.get(Calendar.MONTH)
                && c1.get(Calendar.DAY_OF_MONTH) == c2.get(Calendar.DAY_OF_MONTH));
    }

    public List<Task> getTasks(Calendar time) {//по времени алёрта получаешь лист тасков
        List<Task> res = new ArrayList<>();
        List<UUID> c = this.alerts.getEl(time);
        if (c != null) {
            for (int i = 0; i < c.size(); i++) {
                res.add(tasks.getEl(c.get(i)));
            }
        }
        return res;
    }

    public void removeTask(UUID id) {
        if (this.tasks.contains(id)) {
            Calendar t = tasks.getEl(id).getWtime(); //время алёрта задачи которую хотят удалить
            ArrayList<UUID> a;
            a = alerts.getEl(t);
            a.remove(id);// удалили элемент
            if (!a.isEmpty()) { //если мы не удалили последний элемент
                alerts.addEl(t, a);// вставили новый лист 
            } else {
                alerts.removeEl(t);
            }
            tasks.removeEl(id);//удалили задачу из TaskList
        } else {
            throw new IllegalArgumentException();
        }
    }

    public void changeTask(Task value, UUID id) {
        if ((value == null) || (id == null)) {
            throw new NullPointerException();
        }
        if (this.tasks.contains(id)) {
            this.removeTask(id);
            this.tasks.addEl(id, value);
            this.alerts.addEl(value.getWtime(), id);
        } else {
            throw new IllegalArgumentException();
        }
    }

    public void addTask(Task value) {
        if (value == null) {
            throw new NullPointerException();
        }
        this.alerts.addEl(value.getWtime(), value.getID());
        this.tasks.addEl(value.getID(), value);
    }

    public List<Task> getAll() {//получить все задачи
        List<Task> res = tasks.getAllTasks();
        Collections.sort(res);
        return res;
    }

    public List<Task> getGap(Calendar start, Calendar finish) {//получить задачи за период
        List<Task> res = new ArrayList<>();
        Iterator i = tasks.getAllTasks().iterator();
        Task temp;
        while (i.hasNext()) {
            temp = (Task) i.next();
            if (temp.getStime().after(start) && temp.getStime().before(finish)) {
                res.add(temp);
            }
        }
        Collections.sort(res);
        return res;

    }

    public List<Task> getByDay(Calendar day) {
        Iterator i = tasks.getAllTasks().iterator();
        Task temp;
        List<Task> res = new ArrayList<>();
        while (i.hasNext()) {
            temp = (Task) i.next();
            if (isDayEquals(day, temp.getStime())) {
                res.add(temp);
            }
        }
        Collections.sort(res);
        return res;
    }

    public Calendar getNextTime() {
        ArrayList alert = new ArrayList<>(this.alerts.getKeys());
        Collections.sort(alert);
        int i = 0;
        Calendar res = (Calendar) alert.get(i);
        while (res.before(Calendar.getInstance())) {
            i++;
            res = (Calendar) alert.get(i);
        }
        return res;
    }

    public List<Task> getDeprecatedTasks() {
        ArrayList alert = new ArrayList<>(this.alerts.getKeys());
        Collections.sort(alert);
        List<Task> res = new ArrayList<>();
        Calendar now = Calendar.getInstance();
        int i = 0;
        try {
            while (now.after(alert.get(i))) {
                List<Task> t = this.getTasks((Calendar) alert.get(i));
                for (int j = 0; j < t.size(); j++) {
                    res.add(t.get(j));
                }
                i++;
            }
        } catch (IndexOutOfBoundsException ex) {
        }
        return res;
    }
}